/**
 * 当前会话用户相关类
 */
import store from '../../store/index'
import { JxbHttpClient } from './session'
import SessionUserAdapter from "../../dataAdapter/session/sessionUserAdapter"
/**
 * 当前用户实例的工具类
 * 
 * 请求服务器接口、刷新本地缓存等
 */
export default class SessionUserUtil {

    /**
     * 从服务器端请求用户信息
     * 
     * @returns {Promise<object>} 
     */
    static requestServer() {
        return (new JxbHttpClient()).request('AppMaster/AppletSession/getSessionUserInfo').then(jxbResp => {
            let data = jxbResp.data
            return SessionUserAdapter.convert(data)
        })
    }

    /**
     * 从服务器直接获取当前会话用户信息
     * 
     * @returns {Promise<SessionUser>}
     */
    static getInstanceFromServer(){
        return this.requestServer()
        .then(userData => {
            return new SessionUser(userData)
        })
    }

    /**
     * 获取会话用户实例
     * 
     * 默认从缓存中获取实例，如果失败则从服务器获取
     * @returns {Promise<SessionUser>}
     */
    static getInstance(){
        let prom,sessionUser = store.global('SessionUser')
        if(sessionUser instanceof SessionUser && Object.keys(sessionUser._data).length > 0){
            prom = new Promise(resolve => {
                resolve(sessionUser)
            })
        }else{
            let  userData = this.requestCacheSync()
            if(Object.keys(userData).length === 0){
                // 刷新缓存并获取sessionUser实例
                prom = this.renewCache()
            }else{
                sessionUser = new SessionUser(userData)
                store.global('SessionUser', sessionUser)
                prom = new Promise((resolve)=>{
                    resolve(sessionUser)
                })
            }
        }
        return prom
    }
    /**
     * 获取实例（同步）
     * 
     * 
     * 立即返回会话用户的实例
     * 
     * **Bug&Tips**
     * 
     * + 由于该方法只从内存和本地缓存中获取相关信息，不会向服务器发起请求
     * + 使用该方法时，请确保全局变量中或本地缓存中已经存在相关数据，或者在获取后对结果进行判断
     * + 当本地没有缓存信息时调用了本方法将会返回null
     * @returns {SessionUser}
     */
    static getInstanceSync(){
        let sessionUser = store.global('SessionUser')
        if(sessionUser instanceof SessionUser && Object.keys(sessionUser._data).length > 0){
            // do nothing
        }else{
            // 内存中没有缓存，从本地数据库中获取
            let cacheData = this.requestCacheSync()
            if(Object.keys(cacheData).length > 0){
                sessionUser = new SessionUser(cacheData)
                store.global('SessionUser', sessionUser)
            }else{
                sessionUser = null
            }
        }
        return sessionUser
    }
    /**
     * 获取缓存数据
     * 
     * @returns {object}
     */
    static requestCacheSync(){
        let cacheData = wx.getStorageSync('SessionUser')
        if(typeof cacheData !== 'object'){
            cacheData = {}
        }
        return cacheData
    }
    /**
     * 更新本地缓存
     * 
     * 从服务器同步用户信息到本地缓存
     * 
     * @returns {Promise<SessionUser>} 返回最新的缓存数据
     */
    static renewCache(newInstance = undefined) {
        let instanceDataProm,renewFromServer = false
        let promCacheName = 'sessionUser.renewCacheProm'
        if(newInstance instanceof SessionUser){
            instanceDataProm = Promise.resolve(newInstance)
        }else{
            renewFromServer = true
            instanceDataProm = store.global(promCacheName)
            if(instanceDataProm instanceof Promise){
                // do nothing 复用已存在的Promise实例
                console.debug('并发检测，存在并发的刷新sessionUser的请求，复用已向全局声明的请求', instanceDataProm)
            }else {
                console.debug('并发检测，不存在并发的刷新sessionUser的请求')
                instanceDataProm =  this.getInstanceFromServer()
            }
        }
        let prom =instanceDataProm.then(instance => {
            renewFromServer && console.debug('从远程获取到sessionUser数据，更新本地缓存并存到全局数据中')
            let userData = instance._data
            store.global('SessionUser', instance)
            wx.setStorageSync('SessionUser', userData)
            // 兼容原缓存方式
            // wx.setStorageSync('user_type', userData.accountType);
            wx.setStorageSync('isConsultant', userData.isSalesman);
            wx.setStorageSync('user_id', userData.userId);
            wx.setStorageSync('consultantId', userData.consultantId);
            wx.setStorageSync('phone', userData.phoneNumber);
            wx.setStorageSync('total_balance', {
                is_show_wine_purchase: userData.purchaseCardDisplayed,
                total_balance: userData.purchaseCardBalance
            });
            renewFromServer && store.global(promCacheName, null) // 向全局声明请求已结束
            return instance
        }).catch(error => {
            renewFromServer && store.global(promCacheName, null) // 向全局声明请求已结束
            throw error
        })
        renewFromServer && store.global(promCacheName, instanceDataProm) // 向全局声明请求已存在
        return prom
    }

    /**
     * 
     * @param {SessionUser} user 
     */
    static doUpdate(user){
        let modifiedData = {}
        Object.keys(user._modifiedData).forEach(key => {
            if(user._modifiedData[key]){
                modifiedData[key] = user._modifiedData[key]
            }
        })
        if(Object.keys(modifiedData).length === 0){
            return Promise.resolve(user)
        }
        user._modifiedData = {}
        return (new JxbHttpClient()).request({
            url: 'AppMaster/VipCustomer/updateAccountInfo',
            method: 'POST',
            data: modifiedData
        }).then(jxbResp => {
            this.renewCache().then()
            return jxbResp
        })
        
    }
}

/**
 * 当前会话用户类
 */
export class SessionUser {
    /**
     * @property {object} 源数据
     */
    _data
    /**
     * @property {object} 修改的数据
     */
    _modifiedData
    /**
     * @returns {number} 账户id，账户不存在时为0
     */
    get userId() {
        return isNaN(this._data.userId) ? 0 : parseInt(this._data.userId)
    }
    /**
     * @returns {string} - 实名
     */
    get realName(){
        return this._data.realName + ''
    }
    /**
     * @returns {string} - 昵称
     */
    get nickname(){
        return this._data.nickname + ''
    }
    /**
     * @returns {string} - 展示的名称
     */
    get showName(){
        if(typeof this._data.showName === 'undefined'){
            if(this.realName.indexOf('[微信用户]undefined') > -1 || this.realName.trim() === '[微信用户]'){
                this._data.showName = this.nickname
            }else{
                this._data.showName = this.realName
            }
        }
        return this._data.showName
    }
    /**
     * 姓名未设置的标识
     * 
     * @returns {boolean}
     */
    get notSetName(){
        return !!this._data.notSetName
    }
    /**
     * @returns {string} 头像
     */
    get avatarUrl(){
        return this._data.avatarUrl + ''
    }
    /**
     * 头像未设置的标识
     * 
     * @returns {boolean}
     */
    get notSetAvatar(){
        return !!this._data.notSetAvatar
    }
    /**
     * @returns {string} - 账户类型
     */
    get accountType(){
        return this._data.accountType
    }
    /**
     * @returns {string} - 手机号
     */
    get phoneNumber(){
        return this._data.phoneNumber + ''
    }
    /**
     * @returns {boolean} - 是否为当前商户的业务员 
     */
    get isSalesman(){
        return this._data.isSalesman === true
    }

    /**
     * @returns {number} - 客户作为顾问身份的名片id
     */
    get vCardId(){
        return parseInt(this._data.vCardId)
    }

    /**
     * @returns {number} - 购酒券余额
     */
    get purchaseCardBalance(){
        return parseFloat(this._data.purchaseCardBalance)
    }

    /**
     * @returns {boolean} 购酒券展示状态 true = 展示 false = 隐藏
     */
    get purchaseCardDisplayed(){
        return this._data.purchaseCardDisplayed === true
    }

    /**
     * @returns {number} 销售模式标识 1=零售，2=批发，3=会员(零售)
     */
    get salesModelType(){
        return isNaN(this._data.sale_type) ? 1 : parseInt(this._data.sale_type)
    }

    /**
     * @returns {string} 销售模式名称
     */
    get salesModelTypeName(){
        let nameDic = {1:'零售模式',2:'批发模式',3:'会员模式'},
            name = nameDic[this.salesModelType];
        if(typeof name !== "string"){
            name = "零售模式"
        }
        return name;
    }
    /**
     * @param {object} initData 实例初始化时需要的数据
     */
    constructor(initData = {}) {
        if(typeof initData === 'object' && typeof initData.userId !== 'undefined'){
             this._data = initData
        }
        this._modifiedData = {}
    }

    /**
     * 设置昵称
     * 
     * @param {string}
     */
    set nickname(nickname){
        if(nickname != this.nickname){
            this._data.nickname = this._modifiedData.nickname = nickname
        }
    }

    /**
     * 设置性别
     * 
     * @param {number} 性别id 0=位置 1=男 2=女
     */
    set gender(genderId){
        if(genderId != this.gender){
            this._data.genderId = this._modifiedData.genderId = genderId
        }
    }

    /**
     * 设置头像
     * 
     * @param {string} 
     */
    set avatarUrl(avatarUrl){
        if(avatarUrl != this.avatarUrl){
            this._data.avatarUrl = this._modifiedData.avatarUrl = avatarUrl
        }
    }

    /**
     * 设置手机号
     * 
     * @param {string} 
     */
    set phoneNumber(phoneNumber){
        if(phoneNumber != this.phoneNumber){
            this._data.phoneNumber = this._modifiedData.phoneNumber = phoneNumber
        }
    }
}
